﻿using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using System.Drawing;
using FFmpeg.AutoGen;
using Microsoft.UI.Xaml.Media.Imaging;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Graphics.Canvas;
using Windows.UI.Popups;
using Windows.Graphics.DirectX;
using System.Numerics;
using Microsoft.Graphics.Canvas.Effects;
using FFmpegWinui3.UlitFolder;
using Windows.System.Threading;
using System.Threading.Tasks;
using Microsoft.UI.Dispatching;



// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace FFmpegWinui3
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class FFmpegPage : Page
    {
        string url = @"C:\Users\ludin\Desktop\新建文件夹 (4)\noAuio.mp4";
        DirectXPixelFormat pFormat = DirectXPixelFormat.A8P8;
        List<Data> formats = new List<Data>();
        CanvasBitmap bitmap;

        DispatcherTimer timer = new DispatcherTimer();
        VideoStreamDecoder vsd = null;

        VideoQuene quene = new VideoQuene();
        VideoQuene tempQuene = new VideoQuene();

        double timespan = 0;

        double rate;
        double frameRate;

        Stopwatch st = new Stopwatch();

        public FFmpegPage()
        {
            this.InitializeComponent();
            Init();
        }
        string Duration;
        int MaxValue;
        double frameDuration;
        double lastTime;
        double playTotalTime;
        int playFrameIndex = 0;

        bool playing = false;
        string inputFile = @"C:\Users\ludin\Desktop\新建文件夹 (4)\noAuio.mp4";
        void Init()
        {
            canvas.Draw += (s, e) =>
            {
                if (bitmap != null)
                {
                    GrayscaleEffect gray = new GrayscaleEffect()
                    {
                        Source = bitmap,

                    };

                    var te = Win2DUlit.CalcutateImageCenteredTransform(canvas.ActualSize.X, canvas.ActualSize.Y, bitmap.Size.Width, bitmap.Size.Height);
                    te.Source = gray;
                    e.DrawingSession.DrawImage(te);
                }
            };
            PlayOperate();
            UpdateUi();
        }


        void PlayOperate()
        {
            //播放或粘贴
            play.Click += (s, e) =>
            {
                playing = !playing;
                play.Content = playing ? "暂停" : "播放";
                if (!playing)
                    lastTime = 0;
            };
            //停止
            stop.Click += (s, e) =>
            {
                playing = false;
                vsd = null;
                playFrameIndex = 0;
                playTotalTime = 0;
                lastTime = 0;
            };

            var task = Task.Run(() =>
            {
                while (true)
                {
                    if (playing && vsd == null)
                    {
                        var text = inputFile;

                        vsd = new VideoStreamDecoder(text);
                        rate = vsd.Rate;
                        frameRate = vsd.FrameRate;
                        //视频时长秒
                        var d = (int)vsd.Duration;
                        //视频总时长
                        Duration = $"{((int)(d / 3600 * 60)).ZeroPad(2)}:{((d - d % 60) / 60).ZeroPad(2)}:{(d % 60).ZeroPad(2)}";
                        MaxValue = d;
                        //帧时长,毫秒
                        frameDuration = 1000 / frameRate;
                        playFrameIndex = 0;
                        playTotalTime = 0;
                        lastTime = 0;
                    }
                    else if (vsd != null && playing)
                    {
                        var t = TimeSpan.FromTicks(DateTime.Now.Ticks);
                        var ms = t.TotalMilliseconds;
                        bool nextFrame = false;
                        if (playTotalTime == 0)
                            nextFrame = true;
                        if (lastTime != 0)
                            playTotalTime += ms - lastTime;
                        var index = (int)(playTotalTime / frameDuration);
                        if (index != playFrameIndex)
                        {
                            for (int i = 0; i < index - playFrameIndex - 1; i++)
                            {
                                vsd.TryDecodeNextFrame(out var fame);
                                Debug.WriteLine("丢弃帧" + (playFrameIndex + i));
                            }
                            playFrameIndex = index;
                            nextFrame = true;
                        }
                        lastTime = ms;
                        if (nextFrame)
                        {
                            if (vsd.TryDecodeNextFrame(out var frame))
                            {
                                bitmap = vsd.AVFrameConvertBitmap(frame);
                                canvas.Invalidate();
                            }
                            else
                            {//播放完了
                                vsd = null;
                                playing = false;
                                Debug.WriteLine("播放完了" + (playTotalTime / 1000));
                            }
                        }


                    }
                }
            });
        }

        void UpdateUi()
        {
            var ValueChanged = new RangeBaseValueChangedEventHandler((s, e) =>
             {
                 if (vsd != null)
                 {
                     playing = false;
                     var ss = (int)(e.NewValue);
                     playTotalTime = ss *1000;
                     playFrameIndex =(int)( ss * vsd.FrameRate);
                     vsd.SetSeek(ss);
                     playing = true;
                 }
             });

            timer.Interval = TimeSpan.FromMilliseconds(500);
            timer.Tick += (s, e) =>
            {
                if (!playing)
                    return;
                duration.Text = Duration;
                timeLine.Maximum = MaxValue;
                //毫秒转秒
                var ss = (int)playTotalTime / 1000;
                currentTime.Text = $"{((int)(ss / 3600 * 60)).ZeroPad(2)}:{((ss - ss % 60) / 60).ZeroPad(2)}:{(ss % 60).ZeroPad(2)}";
                timeLine.ValueChanged -= ValueChanged;
                timeLine.Value = ss;
                timeLine.ValueChanged += ValueChanged;

            };
            timer.Start();
            pathBox.TextChanged += (s, e) =>
            {
                inputFile = pathBox.Text;
            };
        }



    }

    public class Data
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public DirectXPixelFormat format;
    }

    public class VideoQuene
    {
        public List<CanvasBitmap> Bitmaps { get; set; } = new List<CanvasBitmap>();

        public bool IsLoad { get; set; }

        public int Count { get; set; }

        public int Index { get; set; }

    }

}
